use std::{fs::File, path::PathBuf};

use anyhow::{bail, Result};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct AppConfig {
    pub server: ServerConfig,
    pub auth: AuthConfig,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ServerConfig {
    pub port: u16,
    pub db_url: String,
    pub base_dir: PathBuf,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct AuthConfig {
    pub sk: String,
    pub pk: String,
}

impl AppConfig {
    // load app.yml
    pub fn load() -> Result<Self> {
        // read ./app.yml,  /etc/config/app.yml, or or from env CHAT_CONFIG
        let config = match (
            File::open("chat.yml"),
            File::open("chat_server/chat.yml"),
            File::open("/etc/config/chat.yml"),
            std::env::var("CHAT_CONFIG"),
        ) {
            (Ok(reader), _, _, _) => serde_yaml::from_reader(reader),
            (_, Ok(reader), _, _) => serde_yaml::from_reader(reader),
            (_, _, Ok(reader), _) => serde_yaml::from_reader(reader),
            (_, _, _, Ok(path)) => serde_yaml::from_reader(File::open(path)?),
            _ => bail!("chat.yml not found"),
        };
        Ok(config?)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_config_load() {
        let config = AppConfig::load().unwrap();
        // println!("{:#?}", config);
        println!("{:#?}", config.server);
        println!("{:#?}", config.auth);
    }
}
